import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';

import '../../../app/constants/app_constants.dart';

/// 缓存修改器
/// 负责处理请求和响应的缓存
class CacheModifier {
  final GetStorage _storage = Get.find<GetStorage>();
  final Duration _cacheDuration;
  
  CacheModifier({Duration? cacheDuration}) 
      : _cacheDuration = cacheDuration ?? AppConstants.cacheDuration;
  
  /// 请求修改器 - 检查是否有缓存可用
  Future<Request> requestModifier(Request request) async {
    // 仅对GET请求进行缓存
    if (request.method != 'GET') return request;
    
    // 检查请求是否指定了不使用缓存
    if (request.headers.containsKey('x-no-cache')) {
      request.headers.remove('x-no-cache');
      return request;
    }
    
    // 生成缓存键
    final String cacheKey = _generateCacheKey(request);
    
    // 检查缓存是否存在且未过期
    final Map<String, dynamic>? cachedData = _storage.read<Map<String, dynamic>>('cache_$cacheKey');
    if (cachedData != null) {
      final DateTime expiryTime = DateTime.parse(cachedData['expiry']);
      if (DateTime.now().isBefore(expiryTime)) {
        // 缓存有效，在请求头中添加标记
        request.headers['x-cache-hit'] = 'true';
        request.headers['x-cached-data'] = json.encode(cachedData['data']);
      }
    }
    
    return request;
  }
  
  /// 响应修改器 - 缓存响应数据
  Future<Response> responseModifier(Request request, Response response) async {
    // 仅对GET请求和成功响应进行缓存
    if (request.method != 'GET' || !response.isOk) return response;
    
    // 检查是否已经命中缓存
    if (request.headers.containsKey('x-cache-hit')) {
      // 如果已经命中缓存，使用缓存数据
      final String cachedDataString = request.headers['x-cached-data'] ?? '';
      if (cachedDataString.isNotEmpty) {
        try {
          final dynamic cachedData = json.decode(cachedDataString);
          return Response(
            statusCode: 200,
            body: cachedData,
            headers: response.headers,
            request: response.request,
          );
        } catch (_) {
          // 解析缓存数据失败，继续使用实际响应
        }
      }
      return response;
    }
    
    // 生成缓存键
    final String cacheKey = _generateCacheKey(request);
    
    // 缓存响应数据
    final DateTime expiryTime = DateTime.now().add(_cacheDuration);
    final Map<String, dynamic> cacheData = {
      'data': response.body,
      'expiry': expiryTime.toIso8601String(),
    };
    
    // 存储缓存
    await _storage.write('cache_$cacheKey', cacheData);
    
    return response;
  }
  
  /// 生成缓存键
  String _generateCacheKey(Request request) {
    final String url = request.url.toString();
    final String queryParams = request.url.queryParameters.toString();
    
    // 使用URL和查询参数生成哈希键
    final String data = '$url|$queryParams';
    final String cacheKey = md5.convert(utf8.encode(data)).toString();
    
    return cacheKey;
  }
  
  /// 清除指定URL的缓存
  Future<void> clearUrlCache(String url) async {
    final pattern = RegExp(r'cache_[a-f0-9]{32}');
    final allKeys = _storage.getKeys();
    
    for (final key in allKeys) {
      if (pattern.hasMatch(key)) {
        final cachedData = _storage.read<Map<String, dynamic>>(key);
        if (cachedData != null && cachedData['url'] == url) {
          await _storage.remove(key);
        }
      }
    }
  }
  
  /// 清除所有缓存
  Future<void> clearAllCache() async {
    final pattern = RegExp(r'cache_[a-f0-9]{32}');
    final allKeys = _storage.getKeys();
    
    for (final key in allKeys) {
      if (pattern.hasMatch(key)) {
        await _storage.remove(key);
      }
    }
  }
}

/// 缓存修改器 - 实现请求响应的缓存功能
Future<Response> cacheResponseModifier(Request request, Response response) async {
  // 只缓存GET请求
  if (request.method != 'GET') {
    return response;
  }
  
  // 获取缓存键
  final cacheKey = request.headers['cache-key'] ?? _generateCacheKey(request);
  
  // 获取缓存时间
  final cacheDuration = _getCacheDuration(request.headers['cache-timeout']);
  
  // 获取是否需要刷新缓存
  final refreshCache = request.headers['refresh-cache'] == 'true';
  
  // 如果响应成功，保存到缓存
  if (response.isOk) {
    _saveToCache(cacheKey, response, cacheDuration);
  }
  
  return response;
}

/// 生成缓存键
String _generateCacheKey(Request request) {
  // 创建一个唯一的缓存键
  final data = utf8.encode('${request.method}:${request.url.toString()}');
  final hash = md5.convert(data);
  return 'cache_${hash.toString()}';
}

/// 从缓存获取响应
Future<Response?> _getFromCache(String cacheKey, bool refreshCache) async {
  if (refreshCache) {
    return null;
  }
  
  try {
    final storage = Get.find<GetStorage>();
    
    // 检查缓存是否存在
    if (!storage.hasData(cacheKey)) {
      return null;
    }
    
    // 获取缓存数据
    final cacheData = storage.read<Map<String, dynamic>>(cacheKey);
    
    if (cacheData == null) {
      return null;
    }
    
    // 检查缓存是否过期
    final expiry = DateTime.parse(cacheData['expiry'] as String);
    if (DateTime.now().isAfter(expiry)) {
      // 缓存已过期，删除
      storage.remove(cacheKey);
      return null;
    }
    
    // 重建响应
    return Response(
      statusCode: cacheData['statusCode'] as int,
      statusText: cacheData['statusText'] as String?,
      body: cacheData['body'],
      headers: Map<String, String>.from(cacheData['headers'] as Map),
    );
  } catch (e) {
    // 如果出错，返回null，触发网络请求
    return null;
  }
}

/// 保存响应到缓存
void _saveToCache(String cacheKey, Response response, Duration cacheDuration) {
  try {
    final storage = Get.find<GetStorage>();
    
    // 计算过期时间
    final expiry = DateTime.now().add(cacheDuration);
    
    // 准备缓存数据
    final cacheData = {
      'statusCode': response.statusCode,
      'statusText': response.statusText,
      'body': response.body,
      'headers': response.headers,
      'expiry': expiry.toIso8601String(),
    };
    
    // 保存到缓存
    storage.write(cacheKey, cacheData);
  } catch (e) {
    // 缓存失败，忽略
  }
}

/// 获取缓存时间
Duration _getCacheDuration(String? cacheTimeout) {
  // 默认缓存5分钟
  const defaultDuration = Duration(minutes: 5);
  
  if (cacheTimeout == null) {
    return defaultDuration;
  }
  
  try {
    final seconds = int.parse(cacheTimeout);
    return Duration(seconds: seconds);
  } catch (e) {
    return defaultDuration;
  }
} 